﻿using System;
using System.Collections.Generic;
using System.Text;

namespace RaisingStudio.Data.Expressions
{
    /// <summary>
    /// condition expression.
    /// </summary>
    [Serializable]
    public class ConditionExpression
    {
        private ExpressionElement expressionElement;
        public ExpressionElement ExpressionElement
        {
            get
            {
                return this.expressionElement;
            }
            set
            {
                this.expressionElement = value;
            }
        }

        private List<SortingExpression> sortingExpressions;
        public List<SortingExpression> SortingExpressions
        {
            get
            {
                if (this.sortingExpressions == null)
                {
                    this.sortingExpressions = new List<SortingExpression>();
                }
                return this.sortingExpressions;
            }
        }

        public bool HasSortingExpressions
        {
            get
            {
                return ((this.sortingExpressions != null) && (this.sortingExpressions.Count > 0));
            }
        }


        #region Constructor
        public ConditionExpression()
        {
        }

        public ConditionExpression(ExpressionElement expressionElement)
            : this()
        {
            this.expressionElement = expressionElement;
        }

        public ConditionExpression(string columnName, ElementOperator expressionOperator, object value)
            : this()
        {
            this.expressionElement = new OperationExpression(columnName, expressionOperator, value);
        }

        public ConditionExpression(OperationElement operationElement, ElementOperator expressionOperator, object value)
            : this()
        {
            this.expressionElement = new OperationExpression(operationElement, expressionOperator, value);
        }

        public ConditionExpression(SortingExpression sortingExpression)
            : this()
        {
            this.OrderBy(sortingExpression);
        }
        #endregion

        public ConditionExpression Where(ExpressionElement expressionElement)
        {
            this.expressionElement = expressionElement;
            return this;
        }

        public ConditionExpression Where(ExpressionElement expressionElement1, RelationOperator relationOperator, ExpressionElement expressionElement2)
        {
            if (expressionElement1 is RelationExpression)
            {
                if (expressionElement2 is RelationExpression)
                {
                    this.expressionElement = new RelationExpression(expressionElement1 as RelationExpression, relationOperator, expressionElement2 as RelationExpression);
                }
                else
                {
                    this.expressionElement = new RelationExpression(expressionElement1 as RelationExpression, relationOperator, expressionElement2 as OperationExpression);
                }
            }
            else
            {
                if (expressionElement2 is RelationExpression)
                {
                    this.expressionElement = new RelationExpression(expressionElement1 as OperationExpression, relationOperator, expressionElement2 as RelationExpression);
                }
                else
                {
                    this.expressionElement = new RelationExpression(expressionElement1 as OperationExpression, relationOperator, expressionElement2 as OperationExpression);
                }
            }
            return this;
        }

        public ConditionExpression OrderBy(SortingExpression sortingExpression)
        {
            if (sortingExpression != null)
            {
                this.SortingExpressions.Add(sortingExpression);
                return this;
            }
            else
            {
                throw new ArgumentNullException("sortingExpression");
            }
        }

        public ConditionExpression OrderBy(ColumnExpression columnExpression)
        {
            if (!object.Equals(columnExpression, null))
            {
                SortingExpression sortingExpression = new SortingExpression((string)columnExpression);
                this.SortingExpressions.Add(sortingExpression);
                return this;
            }
            else
            {
                throw new ArgumentNullException("columnExpression");
            }
        }

        public ConditionExpression OrderBy(string columnName)
        {
            if (columnName != null)
            {
                SortingExpression sortingExpression = new SortingExpression(columnName);
                this.SortingExpressions.Add(sortingExpression);
                return this;
            }
            else
            {
                throw new ArgumentNullException("columnName");
            }
        }

        public ConditionExpression OrderBy(ColumnExpression columnExpression, SortingDirection sortingDirection)
        {
            if (!object.Equals(columnExpression, null))
            {
                SortingExpression sortingExpression = new SortingExpression((string)columnExpression, sortingDirection);
                this.SortingExpressions.Add(sortingExpression);
                return this;
            }
            else
            {
                throw new ArgumentNullException("columnExpression");
            }
        }

        public ConditionExpression OrderBy(string columnName, SortingDirection sortingDirection)
        {
            if (columnName != null)
            {
                SortingExpression sortingExpression = new SortingExpression(columnName, sortingDirection);
                this.SortingExpressions.Add(sortingExpression);
                return this;
            }
            else
            {
                throw new ArgumentNullException("columnName");
            }
        }

        #region type 转换
        public static implicit operator ConditionExpression(OperationExpression value)
        {
            return new ConditionExpression(value);
        }

        public static implicit operator ConditionExpression(RelationExpression value)
        {
            return new ConditionExpression(value);
        }

        public static implicit operator ConditionExpression(SortingExpression value)
        {
            return new ConditionExpression(value);
        }
        #endregion

        #region 符重载
        public static ConditionExpression operator ^(ConditionExpression conditionExpression, SortingExpression sortingExpression)
        {
            return conditionExpression.OrderBy(sortingExpression);
        }

        public static ConditionExpression operator ^(ConditionExpression conditionExpression, ColumnExpression columnExpression)
        {
            return conditionExpression.OrderBy(columnExpression);
        }

        public static ConditionExpression operator ^(ConditionExpression conditionExpression, string columnName)
        {
            return conditionExpression.OrderBy(columnName);
        }
        #endregion
    }
}
